package com.cooper.scraper;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import com.cooper.android.comm.FileUtils;

import android.content.Context;
import android.content.res.AssetManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.util.SparseArray;

public class ScrapersDownTask extends
		AsyncTask<String, Integer, SparseArray<String>> implements
		DownloadCancelled {

	private static final boolean DEBUG = false;

	public interface ScrapersDownListener {

		public void onScrapersDownComplete();
	}

	private static SparseArray<String> scrapers = null;

	public static boolean isReady() {
		return scrapers != null;
	}

	public static String getScraper(int id) {
		if (isReady()) {
			String result = scrapers.get(id);
			if (result != null) {
				return result;
			} else {
				throw new IllegalArgumentException("not this scraper:" + id);
			}
		} else
			throw new IllegalStateException("not run task");
	}

	public static void collectionScraper(Context context, String url,
			ScrapersDownListener listener, boolean onlyWIFI) {
		new ScrapersDownTask(context, listener, onlyWIFI).execute(url);
	}

	private static final String SCAPERS_TAG = "scapers";
	private static final String SCAPER_TAG = "scaper";
	private static final String ASSET_PATH = "scraper";

	private static final String SCAPER_STORE_DIR = ".cooper_soft/scapers/";

	private ScrapersDownListener listener;

	private boolean onlyWIFI = true;

	private Context context;

	private ScrapersDownTask(Context context, ScrapersDownListener listener,
			boolean onlyWIFI) {
		super();
		this.listener = listener;
		this.context = context;
		this.onlyWIFI = onlyWIFI;
	}

	@Override
	protected void onPostExecute(SparseArray<String> result) {

		scrapers = result;
		if ((scrapers != null) && (listener != null) && (!this.isCancelled())) {
			listener.onScrapersDownComplete();
		}
		listener = null;
	}

	private String getScraper(HttpDownload httpDownload, int id, String uri,
			int ver, int targerVer) throws IOException, DownloadException {
		String storeDir = Environment.getExternalStorageDirectory().toString()
				+ "/" + SCAPER_STORE_DIR + "/";
		File storeDirFile = new File(storeDir);
		if (!storeDirFile.exists() || !storeDirFile.isDirectory()) {
			storeDirFile.mkdirs();
		}
		File scraperFile = new File(storeDir + id + ".xml");
		try {
			if (!scraperFile.exists() || !storeDirFile.isFile()) {
				FileUtils.copyAssetsFile(context.getAssets(), ASSET_PATH + "/"
						+ id + ".xml", storeDir + id + ".xml");
			}
			if (scraperFile.exists() && scraperFile.isFile()) {

				String scraper = FileUtils.readTextFile(scraperFile
						.getAbsolutePath());
				int localScraperVer = -1;

				XmlPullParserFactory factory = XmlPullParserFactory
						.newInstance();
				factory.setNamespaceAware(true);
				XmlPullParser xpp = factory.newPullParser();
				xpp.setInput(new StringReader(scraper));
				int eventType = xpp.getEventType();
				while (eventType != XmlPullParser.END_DOCUMENT) {
					if (eventType == XmlPullParser.START_TAG) {
						if ("scraper".equals(xpp.getName())) {
							localScraperVer = Integer.parseInt(xpp
									.getAttributeValue(null, "ver"));
						}
					}
					eventType = xpp.next();
				}

				if (localScraperVer >= ver) {
					return scraper;
				}
			}

		} catch (Exception e) {
			Log.e("ScrapersDownTask", e.getMessage(), e);
		}
		// TODO if minTarget is min
		String page = httpDownload.downloadPage(uri);
		FileUtils.writerTextFile(scraperFile.getAbsolutePath(), page);
		return page;

	}

	@Override
	protected SparseArray<String> doInBackground(String... params) {
		SparseArray<String> result = new SparseArray<String>();

		if (!DEBUG) {

			NetworkInfo networkInfo = ((ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE))
					.getActiveNetworkInfo();
			if ((networkInfo != null)
					&& (NetworkInfo.State.CONNECTED == networkInfo.getState())
					&& (!onlyWIFI || (networkInfo.getType() == ConnectivityManager.TYPE_WIFI))
					&& (Environment.getExternalStorageState()
							.equals(Environment.MEDIA_MOUNTED))) {

				HttpDownload httpDownload = new HttpDownload(
						new DownloadParams(this));
				try {
					String page = httpDownload.downloadPage(params[0], false);

					if (isCancelled() || page == null || "".equals(page)) {
						return result;
					}
					XmlPullParserFactory factory = XmlPullParserFactory
							.newInstance();
					factory.setNamespaceAware(true);
					XmlPullParser xpp = factory.newPullParser();
					xpp.setInput(new StringReader(page));
					int eventType = xpp.getEventType();
					boolean inScapersTag = false;

					while (eventType != XmlPullParser.END_DOCUMENT) {
						if (isCancelled()) {
							return null;
						}
						if (eventType == XmlPullParser.START_TAG) {
							if (SCAPERS_TAG.equals(xpp.getName())) {
								inScapersTag = true;
							} else if (inScapersTag
									&& SCAPER_TAG.equals(xpp.getName())) {

								int id = Integer.parseInt(xpp
										.getAttributeValue(null, "id"));
								result.put(
										id,
										getScraper(httpDownload, id,
												xpp.getAttributeValue(null,
														"uri"),
												Integer.parseInt(xpp
														.getAttributeValue(
																null, "ver")),
												Integer.parseInt(xpp
														.getAttributeValue(
																null,
																"minTarget"))));
							}
						} else if (eventType == XmlPullParser.END_TAG) {
							if (inScapersTag
									&& SCAPERS_TAG.equals(xpp.getName())) {
								inScapersTag = false;
							}
						}
						eventType = xpp.next();
					}
					if (result.size() > 0)
						return result;
				} catch (Exception exception) {
					Log.e("ScrapersDownTask", exception.getMessage(), exception);
				}
			}
		}
		AssetManager am = context.getAssets();
		try {
			String[] assFiles = am.list(ASSET_PATH);
			for (int i = 0; i < assFiles.length; i++) {
				if (assFiles[i].trim().matches("\\d+\\.xml")) {
					Matcher m = Pattern.compile("(\\d+)\\.xml").matcher(
							assFiles[i]);
					if (m.find()) {

						BufferedReader reader = new BufferedReader(
								new InputStreamReader(am.open(ASSET_PATH + "/"
										+ assFiles[i])));
						try {
							StringBuffer scraperTxt = new StringBuffer();
							String line = reader.readLine();
							while (line != null) {
								scraperTxt.append(line);
								scraperTxt.append("\n");
								line = reader.readLine();
							}
							result.put(Integer.parseInt(m.group(1)),
									scraperTxt.toString());
						} finally {
							reader.close();
						}
					}
				}
			}
		} catch (IOException e) {
			Log.e("ScrapersDownTask", e.getMessage(), e);
		}

		return result;
	}

}
